
export const to2 = (number) => {
  return parseFloat(number.toFixed(2))
};

/**
 * ## randomString
 * 按给定长度形成一个包含字母与数字的随机字符串
 * @param {number} len 
 */
export const randomString = (len) => {
  return Math.random().toString(35).slice(2, 2+len);
}

/**
 * ## randomIndex
 * 从列表中随机选择一个元素的index
 * @param {Array} list 
 */
export const randomIndex = (list, {min=0, max=list.length}={}) => {

  const index = list.length * Math.random()

  return Math.floor(Math.min(Math.max(index, min), max < 0 ? list.length - 1 + max : max));
}

/**
 * ## randomSelect
 * 从列表中随机选择若干不重复的元素
 * @param {Array} list 列表
 * @param {number} number 索要选择的元素数量。
 * ----
 * - 如果number为0到1之间的实数，则取其与列表长度乘积之floor；如果为大于1的实数，则为实际的数量；如果多于list的长度，则取list的长度。
 */
export const randomSelect = (list, number = 0, {Cons=Array, remaining=false}={}) => {

  if (number === 0 || number === 1) {
    return list[randomIndex(list)];
  }

  const actualNumber = number > 0 && number < 1
    ? Math.floor(list.length * number)
    : Math.min(number, list.length)

  const copy = list.slice();
  const res = new Cons();
  for (let i = 0; i < actualNumber; i++) {
    const [elem] = copy.splice(randomIndex(copy), 1);
    res.push(elem);
  }

  if (remaining) {
    return {selected: res, rest: copy};
  }

  return res;
}

export const createEntry = ({curr, code, name, itemCode, itemName, destCode, destName}={}, {dir='dr', dirType='single', item=false}={}) => {

  const cr = Math.random() * 100;
  const dr = Math.random() * 100;

  let balance;
  switch(dirType) {
    case 'direction':
      const opening = Math.random() * 100;
      const closing = to2(opening + (dir === 'dr' ? to2(dr - cr) : to2(cr - dr)));
      balance = {
        opening,
        closing,
        openingDir: dir,
        closingDir: dir
      };
      break;
    default:
      const [openingCr, openingDr] = dir === 'cr' ? [to2(Math.random() * 100), 0] : [0, to2(Math.random() * 100)];
      const [closingCr, closingDr] = [to2(openingCr + cr), to2(openingDr + dr)];
      balance = {
        openingCr, openingDr,
        closingCr, closingDr
      };
  }


  return {
    code: (curr?.code ?? code) ?? randomString(4),
    name: (curr?.name ?? name) ?? randomString(24),
    itemCode: itemCode ?? (item ? randomString(4) : undefined),
    itemName: itemName ?? (item ? randomString(24) : undefined),
    destCode: destCode ?? randomString(4),
    destName: destName ?? randomString(24),
    cr,
    dr,
    ...balance
  }
}

export const createNestedEntryList = ({initialEntryData, attempts=100}={}) => {
  let counter = attempts;
  let cateList = [];

  cateList.push(initialEntryData ?? createEntry());

  while(counter > 0) {

    const elem = randomSelect(cateList);
    const newEntry = createEntry({
      code: `${elem.code}${randomString(4)}`,
    });

    if (!cateList.map(({code}) => code).includes(newEntry.code)) {
      cateList.push(newEntry);
    }

    counter --;
  }

  cateList.shift()
  return cateList;
}

